package com.ice_col.unlockview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

/**
 * Created by Administrator on 2015/10/10 0010.
 */
public class UnclockView extends View {

    private Point[][] mPoints=new Point[3][3];

    private boolean isPointsShowed=false;

    private boolean isStarted=false;

    //the selected point when unlock;
    private List<Point> mSelectedPoint;

    //the position of finger when unlock
    private float mCurrentX=0;
    private float mCurrentY=0;


    private Paint mPointPaint;
    private Paint mLinePaint;

    private IFinshPaint mCallback;


    public interface IFinshPaint{
        void onUserFinshPaint();
    }

    public UnclockView(Context context) {
        super(context);

    }

    public UnclockView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public UnclockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(mLinePaint==null){
            mLinePaint=new Paint();
            mLinePaint.setColor(Color.GREEN);
            mLinePaint.setStrokeWidth(3.0f);
            mLinePaint.setAntiAlias(true);
        }
        if(mPointPaint==null){
            mPointPaint=new Paint();
            mPointPaint.setAntiAlias(true);
        }
        if(!isPointsShowed){
            initPoints();
            isPointsShowed=true;
        }
        drawPoints(canvas);
        drawUserPaint(canvas);

    }

    private void drawUserPaint(Canvas canvas){
        if(isStarted){
            mPointPaint.setColor(Color.GREEN);
            if(mSelectedPoint!=null&&!mSelectedPoint.isEmpty()){
                Point lastPoint=mSelectedPoint.get(mSelectedPoint.size()-1);
                //draw the last line
                canvas.drawLine(lastPoint.getmPositionX(), lastPoint.getmPositionY(), mCurrentX, mCurrentY, mPointPaint);
                System.out.println("drawing line");
                if(mSelectedPoint.size()>=2){
                    for(int i=0;i<mSelectedPoint.size()-1;i++){
                        Point prePoint=mSelectedPoint.get(i);
                        Point nextPoint=mSelectedPoint.get(i+1);
                        canvas.drawLine(prePoint.getmPositionX(), prePoint.getmPositionY(),
                                nextPoint.getmPositionX(), nextPoint.getmPositionY(), mLinePaint);
                    }
                }
            }
        }
    }
    private void drawPoints(Canvas canvas){
        for(int i=0;i<mPoints.length;i++){
            for(int j=0,k=mPoints[i].length;j<k;j++){
                Point tmpPoint=mPoints[i][j];
                if(tmpPoint.isConnected()){
                    mPointPaint.setColor(Color.GREEN);
                }else{
                    mPointPaint.setColor(Color.RED);
                }
                canvas.drawCircle(mPoints[i][j].getmPositionX(),
                        mPoints[i][j].getmPositionY(), Point.mRaduis, mPointPaint);
            }
        }
    }


    private void initPoints(){
        float width=getWidth();
        float height=getHeight();
        width=width>height?height:width;
        for(int i=0;i<mPoints.length;i++){
            for(int j=0,k=mPoints[i].length;j<k;j++){
                mPoints[i][j]=new Point();
                mPoints[i][j].setmPositionX(width * (j + 1) / 4 - Point.mRaduis );
                mPoints[i][j].setmPositionY(width * (i + 1) / 4 - Point.mRaduis);
                mPoints[i][j].setNum(i*3+j+1);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mCurrentX=event.getX();
        mCurrentY=event.getY();
        Point tmpPoint;
        switch (event.getAction()){
            case MotionEvent.ACTION_CANCEL:
                Log.i("Tag","action cancel");
                isStarted=false;
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i("Tag","action move");
                tmpPoint=isTouchPoint();
                if(null!=tmpPoint&&!tmpPoint.isConnected()){
                    tmpPoint.setIsConnected(true);
                    mSelectedPoint.add(tmpPoint);
                }
                break;
            case MotionEvent.ACTION_DOWN:
                Log.i("Tag","action down");
                isStarted=true;
                if(mSelectedPoint==null) {
                    mSelectedPoint = new ArrayList<>();
                }else{
                    mSelectedPoint.clear();
                }
                tmpPoint=isTouchPoint();
                if(tmpPoint!=null){
                    mSelectedPoint.add(tmpPoint);
                    tmpPoint.setIsConnected(true);
                }
                break;
            case MotionEvent.ACTION_UP:
                Log.i("Tag","action up");
                isStarted=false;
                if(mCallback!=null){
                    mCallback.onUserFinshPaint();
                }
                getPaintSequence();
                initPointsStatus();
                System.out.println(getPaintSequence());
                break;
        }
        invalidate();
        return true;
    }

    private String getPaintSequence(){
        StringBuffer stringBuffer=new StringBuffer();
        for(int i=0;i<mSelectedPoint.size();i++){
            stringBuffer.append(String.valueOf(mSelectedPoint.get(i).getNum()));
        }
        return stringBuffer.toString();
    }

    private void initPointsStatus(){
        for(int i=0;i<mPoints.length;i++){
            for(int j=0,k=mPoints[i].length;j<k;j++){
               mPoints[i][j].setIsConnected(false);
            }
        }
    }

    private Point isTouchPoint(){
        for(int i=0;i<mPoints.length;i++){
            for(int j=0,k=mPoints[i].length;j<k;j++){
                Point tmpPoint=mPoints[i][j];
                if(Math.abs(mCurrentX-tmpPoint.getmPositionX())<=Point.mRaduis
                        &&Math.abs(mCurrentY-tmpPoint.getmPositionY())<=Point.mRaduis){
                    System.out.println("Position:"+tmpPoint.getmPositionX()+tmpPoint.getmPositionY());
                    return tmpPoint;
                }
            }
        }
        return null;
    }

    class Point{
        private float mPositionX;
        private float mPositionY;
        private boolean isConnected=false;
        public static final float mRaduis=20;
        private int num;

        public float getmPositionY() {
            return mPositionY;
        }

        public void setmPositionY(float mPositionY) {
            this.mPositionY = mPositionY;
        }

        public boolean isConnected() {
            return isConnected;
        }

        public void setIsConnected(boolean isConnected) {
            this.isConnected = isConnected;
        }

        public float getmPositionX() {
            return mPositionX;
        }

        public void setmPositionX(float mPositionX) {
            this.mPositionX = mPositionX;
        }

        public int getNum() {
            return num;
        }

        public void setNum(int num) {
            this.num = num;
        }
    }
}
